#pragma once

// Base header for calculating model paras

#include <utils/Concepts.h>
#include <utils/config.h>

namespace solar
{
    class CommonPara;
    class ScenePara;
    class SimulationPara;
    class Sun;
    class HeliostatPara;
    class Receiver;
    class Heliostat;

    template <typename T>
    void computeSigma(SimulationPara* /*unused*/, ScenePara* /*unused*/, HeliostatPara* /*unused*/,
                      CommonPara* /*unused*/, Sun* /*unused*/, Heliostat* /*unused*/,
                      Receiver* /*unused*/, T* /*unused*/)
    {
        static_assert(false, "Don't use this generic **unimplemented** version, include the "
                             "corresponding header for detailed implementation");
    }

    template <ClassWithComputeSigma T>
    void computeSigma(SimulationPara* simulation_para, ScenePara* scene_para,
                      HeliostatPara* heliostat_para, CommonPara* common_para, Sun* sun,
                      Heliostat* heliostat, Receiver* receiver, T* ptr)
    {
        ptr->computeSigma(simulation_para, scene_para, heliostat_para, common_para, sun, heliostat,
                          receiver);
    }

    using ComputeSigmaCallback = void(*)(void *);

    template <typename T>
    void computeSigma(SimulationPara* /*unused*/, ScenePara* /*unused*/,
                      SOLAR_ARRAY_ARG HeliostatPara* /*unused*/, CommonPara* /*unused*/,
                      Sun* /*unused*/, SOLAR_ARRAY_ARG Heliostat* /*unused*/, Receiver* /*unused*/,
                      std::size_t /*unused*/, SOLAR_ARRAY_ARG T* /*unused*/, ComputeSigmaCallback /*unused*/)
    {
        static_assert(false, "Don't use this generic **unimplemented** version, include the "
                             "corresponding header for detailed implementation");
    }

    template <ClassWithComputeSigma2 T>
    void computeSigma(SimulationPara* simulation_para, ScenePara* scene_para,
                      SOLAR_ARRAY_ARG HeliostatPara* heliostat_para, CommonPara* common_para,
                      Sun* sun, SOLAR_ARRAY_ARG Heliostat* heliostat, Receiver* receiver,
                      std::size_t num_helios, T* ptr, ComputeSigmaCallback callback)
    {
        ptr->computeSigma(simulation_para, scene_para, heliostat_para, common_para, sun, heliostat,
                          receiver, num_helios, callback);
    }

} // namespace solar
